﻿#region Usings

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using FeedReader.Data;
using FeedReader.Enums;

#endregion

namespace FeedReader.Xml
{
    internal static class FeedRdfXmlParser
    {
        private static string _cacheFolder;
        private static bool _useCache;

        internal static bool TryParse(XDocument xmlFeed, ref Feed feed, string cacheFolder, bool downloadImages, List<FeedItemFilter> itemFilters)
        {
            _cacheFolder = cacheFolder;
            _useCache = true;
            return TryParse(xmlFeed, ref feed, downloadImages, itemFilters);
        }

        internal static bool TryParse(XDocument xmlFeed, ref Feed feed, bool downloadImages, List<FeedItemFilter> itemFilters)
        {
            Feed rFeed = feed;
            XNamespace rdf = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
            XElement element = xmlFeed.Element(rdf + "RDF");

            if (element != null)
            {
                LogEvents.InvokeOnDebug(new FeedArgs("The feed is a RDF feed. Now parsing the xml data"));
                XNamespace dc = "http://purl.org/dc/elements/1.1/";
                XNamespace d = "http://purl.org/rss/1.0/";
                XNamespace nsContent = "http://purl.org/rss/1.0/modules/content/";
                XNamespace nsImage = "http://purl.org/rss/1.0/modules/image/";


                rFeed.ImagePath =
                    FeedXmlParser.ParseString(
                        xmlFeed.Descendants(d + "channel").Elements(d + "image").Attributes("resource"), "channel/image/attribute[resource]");
                rFeed.Description =
                    Utils.Clean(FeedXmlParser.ParseString(xmlFeed.Descendants(d + "channel").Elements(d + "description"), "channel/description"));
                rFeed.Title =
                    Utils.Clean(FeedXmlParser.ParseString(xmlFeed.Descendants(d + "channel").Elements(d + "title"), "channel/title"));

                try
                {
                    FeedItem feedItem;
                    int i = 1;
                    foreach (XElement item in xmlFeed.Descendants(d + "item"))
                    {
                        feedItem = new FeedItem();
                        feedItem.Author = Utils.Clean(FeedXmlParser.ParseString(item.Element(d + "author"), "item[" + i + "]/author"));
                        feedItem.Title = Utils.Clean(FeedXmlParser.ParseString(item.Element(d + "title"), "item[" + i + "]/title"), true, false, true, true, itemFilters);
                        feedItem.Url = FeedXmlParser.ParseString(item.Element(d + "link"), "item[" + i + "]/link").Trim();
                        feedItem.PublishDate = FeedXmlParser.ParseDateTime(item.Element(dc + "date"), "item[" + i + "]/date");

                        LogEvents.InvokeOnDebug(new FeedArgs("Try to get feed[" + rFeed.Title + "][" + feedItem.Title + "][" + i + "] item image..."));
                        feedItem.ImagePath = FeedXmlParser.ParseString(item.Element(nsImage + "item"), d + "about", "item[" + i + "]/attribute[about]");
                        if (Path.GetExtension(feedItem.ImagePath) == ".gif" || Path.GetExtension(feedItem.ImagePath) == ".bmp" ||
                            Path.GetExtension(feedItem.ImagePath) == ".jpg" || Path.GetExtension(feedItem.ImagePath) == ".png" ||
                            Path.GetExtension(feedItem.ImagePath) == ".jpeg")
                        {
                            LogEvents.InvokeOnDebug(new FeedArgs("Enclosure of feed[" + rFeed.Title + "][" + feedItem.Title + "][" + i + "] item is an image. Parse image url..."));
                        }
                        else
                        {
                            LogEvents.InvokeOnDebug(new FeedArgs("Enclosure of feed[" + rFeed.Title + "][" + feedItem.Title + "][" + i + "] item is not an image. Skipping parsing image url..."));
                            feedItem.ImagePath = string.Empty;
                        }
                        string description = FeedXmlParser.ParseString(item.Element(d + "description"), "item[" + i + "]/description");
                        description = Utils.Clean(description, false, true, true, false, itemFilters);
                        if (string.IsNullOrEmpty(feedItem.ImagePath))
                        {
                            LogEvents.InvokeOnDebug(new FeedArgs("Try to get feed[" + rFeed.Title + "][" + feedItem.Title + "][" + i + "] image out of description field..."));
                            feedItem.ImagePath = Utils.GetImageOutOfDescription(description);
                        }
                        feedItem.Description = Utils.Clean(description, false, true, false, true, itemFilters) == "" ?
                                               Utils.Clean(Utils.GetCdata(FeedXmlParser.ParseString(item.Element(nsContent + "encoded"), "item[" + i + "]/encoded")), false, true, false, true, itemFilters) :
                                               Utils.Clean(description, false, true, false, true, itemFilters);
                        rFeed.Items.Add(feedItem);
                        i++;
                    }
                    /* rFeed.Items = (from item in xmlFeed.Descendants(d + "item")
                                   select new FeedItem
                                              {
                                                  Author = FeedXmlParser.ParseString(item.Element(d + "author"), "item/author"),
                                                  Title =
                                                      Utils.Clean(FeedXmlParser.ParseString(item.Element(d + "title"), "item/title")),
                                                  UrlPath = FeedXmlParser.ParseString(item.Element(d + "link"), "item/link"),
                                                  PublishDate = FeedXmlParser.ParseDateTime(item.Element(dc + "date"), "item/date"),
                                                  Description = Utils.Clean(FeedXmlParser.ParseString(item.Element(d + "description"), "item/description")) == "" ?
                                                              Utils.Clean(Utils.GetCdata(FeedXmlParser.ParseString(item.Element(nsContent + "encoded"), "item/encoded"))):
                                                              Utils.Clean(FeedXmlParser.ParseString(item.Element(d + "description"), "item/description")),
                                                  ImagePath = FeedXmlParser.ParseString(item.Element(nsImage + "item"), d + "about", "item/attribute[about]"),
                                              }).OrderByDescending(feedItem => feedItem.PublishDate).ToList();*/
                    
                    if (downloadImages)
                    {
                        LogEvents.InvokeOnInfo(new FeedArgs("Try to get feed images either from cache or from download links"));
                        feed = _useCache ? Utils.DownloadImages(rFeed, _cacheFolder) : Utils.DownloadImages(rFeed);
                    }
                    else feed = rFeed;
                    feed.Items = feed.Items.OrderByDescending(fItem => fItem.PublishDate).ToList();
                    LogEvents.InvokeOnDebug(new FeedArgs("Parsing of RDF feed done. See above for possibly errors or warnings"));
                    return true;
                }
                catch (Exception ex)
                {
                    LogEvents.InvokeOnError(new FeedArgs("Error parsing RDF feed", ex.Message, ex.StackTrace));
                    //feed = null;
                    return false;
                }
            }
            LogEvents.InvokeOnDebug(new FeedArgs("This is not a RDF feed or the downloaded xml file is not a valid feed"));
            //feed = null;
            return false;
        }
    }
}